home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / drgnsmth.cpt / Dragonsmith 1.1 / Base files / Utilities / FileUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-10  |  10.9 KB  |  303 lines

  1. /*
  2.     FileUtils.c
  3.     
  4.     Created    05 May 1992    Extracted from Dragon.c
  5.     Modified    28 May 1992    Changed parameters of FREFTypes
  6.                         Other very minor changes
  7.             29 May 1992    Added RefNumToFSSpec function ╤ I finally figured out how to get an FSSpec from a path refNum
  8.             02 Aug 1992    Added FSpToPB, FSpToPBCatInfo, PBToFSp, and PBToFSpCatInfo ╤ but they haven't been tested!
  9.             05 Aug 1992    Extensive rewrites and some testing of the FSSpec <=> PBRecUnion conversion functions ╤ what I
  10.                             tested seemed to work just fine, but then I didn't test directories╔
  11.             06 Aug 1992    Tuned up conversion functions
  12.             09 Aug 1992    FREFTypes now takes a parameter ╤ the refnum of the resource fork to look in
  13.                         Added FSpFindFolder
  14.             16 Aug 1992    Fixed problems with ioDirID and ioFDirIndex in PBToFSpCatInfo
  15.             04 Sep 1992    Added FSpRefreshFinderDisplay (and it works!)
  16.             09 Sep 1992    Fixed bug in FREFTypes ╤ it returned garbage if there were no 'FREF' resources
  17.             11 Sep 1992    Extracted PBToFSp, FSpType, and FSpOpenableType ╤ Dragonsmith doesn't need them
  18.  
  19.     Copyright ⌐ 1992 by Paul M. Hoffman
  20.     Send comments or suggestions to paul.hoffman@um.cc.umich.edu
  21.     
  22.     This source code may be freely used, altered, and distributed in any way as long as:
  23.         1.    It is GIVEN away rather than sold (except as expressly permitted by the author)
  24.         2.    This statement and the above copyright notice are left intact.
  25.  
  26. */
  27.  
  28. #include    "FileUtils.h"
  29. #include    "StringUtils.h"
  30.  
  31. void FSpRefreshFinderDisplay (FSSpec *fss)
  32. {
  33.     // Given an FSSpec to a file, tell the Finder to update its display of the file's icon ╤ also works for directories
  34.     // There will be a brief delay before the change is shown.  Experience indicates that the delay is noticeably longer
  35.     //    if the only change is in the case (upper vs. lower) of the file's name
  36.     
  37.     CInfoPBRec    pb;
  38.     OSErr        err;
  39.     long            secs;
  40.     
  41.     // Fill in the parameter block so we get info on the parent directory rather than the file/folder itself
  42.     pb.hFileInfo.ioCompletion = NULL;
  43.     pb.hFileInfo.ioNamePtr = NULL;
  44.     pb.hFileInfo.ioVRefNum = fss->vRefNum;
  45.     pb.hFileInfo.ioFDirIndex = 0;
  46.     pb.hFileInfo.ioDirID = fss->parID;
  47.     
  48.     // Get info on the parent directory
  49.     if (PBGetCatInfoSync (&pb) == noErr) {
  50.         // Now change the parent directory's modified date
  51.         GetDateTime (&secs);
  52.         pb.dirInfo.ioDrMdDat = (unsigned long) secs;
  53.         (void) PBSetCatInfoSync (&pb);
  54.     }
  55. }
  56.  
  57. OSErr FSpOpenDataFork (FSSpec *fss, short *refNum, char *perm)
  58. {
  59.     // Open a file's data fork with fsRdPerm or (if possible) fsRdWrPerm
  60.     
  61.     OSErr    err;
  62.     char        permWanted = *perm;
  63.     
  64.     err = FSpOpenDF (fss, *perm, refNum);
  65.     if (err == noErr)
  66.         return err;
  67.     if ((err == opWrErr || err == permErr) && *perm == fsRdWrPerm) {
  68.         err = FSpOpenDF (fss, fsRdPerm, refNum);
  69.         *perm = fsRdPerm;
  70.     }
  71.     return err;
  72. }
  73.  
  74. OSErr FSpOpenResFork (FSSpec *fss, short *refNum, char *perm)
  75. {
  76.     // Open a file's resource fork with fsRdPerm or (if possible) fsRdWrPerm
  77.     
  78.     OSErr    err;
  79.     char        permWanted = *perm;
  80.     
  81.     *refNum = FSpOpenResFile (fss, *perm);
  82.     err = ResError ();
  83.     if (err == noErr)
  84.         return err;
  85.     if ((err == opWrErr || err == permErr) && *perm == fsRdWrPerm) {
  86.         *refNum = FSpOpenResFile (fss, fsRdPerm);
  87.         err = ResError ();
  88.         *perm = fsRdPerm;
  89.     }
  90.     return err;
  91. }
  92.  
  93. OSErr FSpFindFolder (OSType folderType, FSSpec *fss)
  94. {
  95.     // NOTE:    This function does NOT return an FSSpec to the folder in question; rather, it returns an FSSpec to an unnamed
  96.     //        file IN THAT FOLDER.  In other words, just fill in the name field of the FSSpec returned to get at a file in the folder
  97.     // If an error happens, *fss is not affected
  98.     
  99.     short    foundVRefNum;
  100.     long        foundDirID;
  101.     OSErr    err;
  102.     
  103.     err = FindFolder (kOnSystemDisk, folderType, kCreateFolder, &foundVRefNum, &foundDirID);
  104.     if (err == noErr) {
  105.         fss->vRefNum = foundVRefNum;
  106.         fss->parID = foundDirID;
  107.     }
  108.     return err;
  109. }
  110.  
  111. OSErr FSpToPB (PBRecUnion *pb, FSSpec *fss, Boolean resolveAFs, Boolean followAFChain, Boolean *wasAF)
  112. {
  113.     OSErr    err = noErr;
  114.     Boolean    isFolder;
  115.     
  116.     if (resolveAFs)
  117.         err = ResolveAliasFile (fss, followAFChain, &isFolder, wasAF);
  118.     if (err == noErr) {
  119.         pb->h.fileParam.ioVRefNum = fss->vRefNum;
  120.         pb->h.fileParam.ioDirID = fss->parID;
  121.         SmartCopyPStr (fss->name, pb->h.fileParam.ioNamePtr);    // This ensures that .ioNamePtr points to a string exactly
  122.                                                         //    equivalent to fss->name
  123.     }
  124.     return err;
  125. }
  126.  
  127. OSErr FSpToPBCatInfo (PBRecUnion *pb, FSSpec *fss, Boolean resolveAFs, Boolean followAFChain, Boolean *wasAF)
  128. {
  129.     OSErr    err = noErr;
  130.     Boolean    isFolder;
  131.     
  132.     err = FSpToPB (pb, fss, resolveAFs, followAFChain, wasAF);
  133.     if (err == noErr) {
  134.         pb->c.hFileInfo.ioFDirIndex = 0;    // No indexing
  135.         err = PBGetCatInfoSync (pb);
  136.     }
  137.     return err;
  138. }
  139.  
  140. OSErr PBToFSpCatInfo (PBRecUnion *pb, FSSpec *fss, Boolean resolveAFs, Boolean followAFChain, Boolean *wasAF)
  141. {    
  142.     // NOTE:    *wasAF will contain garbage if the error returned != noErr
  143.  
  144.     OSErr    err;
  145.     long        dirIDOrFileNum, ioDirIDWas;
  146.     Ptr        ioMiscWas;
  147.     short    ioFDirIndexWas;
  148.     Boolean    isFolder;
  149.     
  150.     // ASSERT ╤ the ioNamePtr, ioVRefNum, ioFDirIndex, and ioDirID fields in *pb are valid
  151.     
  152.     err = PBGetCatInfoSync (pb);
  153.     if (err == noErr) {
  154.  
  155.         // ASSERT ╤    Most of the fields in *pb are now valid (unless the doc is an alias file and resolveAFs == TRUE,
  156.         //            in which case we've got the wrong file ╤ calling ResolveAliasFile below will fix this, though, so don't worry!)
  157.     
  158.         // Now we're ready to make an FSSpec out of the paramblock
  159.         
  160.         ioDirIDWas = pb->c.hFileInfo.ioDirID;                // Save the file number/directory ID returned by PBGetCatInfo
  161.         pb->c.hFileInfo.ioDirID = pb->c.hFileInfo.ioFlParID;    // Restore the parent ID so PBMakeFSSpec will work
  162.         
  163.         ioMiscWas = pb->h.ioParam.ioMisc;        // Save the value in pb->ioParam.ioMisc ╤ it occupies the same space
  164.                                             //    as pb->fileParam.ioFDirIndex, .ioFlAttrib, and .ioFlVersNum
  165.         pb->h.ioParam.ioMisc = (Ptr) fss;            // This tells the File Manager where to put the resulting FSSpec
  166.         err = PBMakeFSSpecSync (pb);
  167.         pb->h.ioParam.ioMisc = ioMiscWas;        // Restore pb->ioParam.ioMisc (and thus .ioFDirIndex, .ioFlAttrib, and .ioFlVersNum)
  168.     
  169.         // If resolveAFs == TRUE, then we need to check to see if this is an alias file ╤ we can't
  170.         //    eliminate any file types, since in the future there may exist aliases to things (like maybe
  171.         //    mailboxes, in OCE) that didn't exist at the time this code was written.  We can, however,
  172.         //    be sure that only files can be alias files (kinda obvious, ain't it?)
  173.         
  174.         *wasAF = FALSE;
  175.  
  176.         if (err == noErr && resolveAFs && PBIsAliasFile (pb)) {
  177.             err = ResolveAliasFile (fss, followAFChain, &isFolder, wasAF);
  178.             if (err == noErr && *wasAF) {
  179.                 // If this was an alias file, we need to call PBGetCatInfo once more for the actual file
  180.                 pb->c.hFileInfo.ioVRefNum = fss->vRefNum;
  181.                 pb->c.hFileInfo.ioDirID = fss->parID;
  182.                 
  183.                 ioFDirIndexWas = pb->c.hFileInfo.ioFDirIndex;    // Save the value in ioFDirIndex
  184.                 pb->c.hFileInfo.ioFDirIndex = 0;                // Zero ioFDirIndex so PBGetCatInfo won't use indexing
  185.                 
  186.                 // You don't need to copy fss->name to .ioNamePtr here ╤ PBGetCatInfo will do it for us
  187.                 err = PBGetCatInfoSync (pb);
  188.                 
  189.                 pb->c.hFileInfo.ioFDirIndex = ioFDirIndexWas;    // Restore ioFDirIndex
  190.             }
  191.         } else
  192.             pb->c.hFileInfo.ioDirID = ioDirIDWas;            // Restore the file number/directory ID
  193.     }
  194.     return err;
  195. }
  196.  
  197. TypeListHndl FREFTypes (short resFork)
  198. {
  199.     short        numFREFs, frefNum, numTypes = 0, saveResFork;
  200.     OSType        type, **fref;
  201.     TypeListHndl    typesHndl = NULL;
  202.     
  203.     if (resFork == kInvalidRefNum)
  204.         return NULL;
  205.         
  206.     saveResFork = CurResFile ();        // Save the current order of open resource forks
  207.     UseResFile (resFork);            // We'll read 'FREF' resources just from this file, since there may be any number of
  208.                                 //    open allication files and we don't want to end up with 'FREF's from all of them!
  209.     numFREFs = Count1Resources ('FREF');
  210.     if (numFREFs != 0) {
  211.         typesHndl = (TypeListHndl) NewHandle (numFREFs * sizeof (OSType) + sizeof (short));
  212.         if (typesHndl != NULL) {
  213.             for (numTypes = 0, frefNum = 1; frefNum <= numFREFs; frefNum++) {
  214.                 fref = (OSType **) Get1IndResource ('FREF', frefNum);
  215.                 if (fref != NULL) {
  216.                     type = **fref;
  217.                     DisposHandle ((Handle) fref);
  218.                     if (type != 'APPL')                            // Don't count the 'APPL' type ╤ nearly all
  219.                         (*typesHndl)->type[numTypes++] = type;    //    applications have an 'FREF' for this
  220.                 }
  221.             }
  222.             if (numTypes < numFREFs)
  223.                 SetHandleSize ((Handle) typesHndl, numTypes * sizeof (OSType) + sizeof (short));
  224.         }
  225.     }    
  226.     if (typesHndl != NULL)
  227.         (*typesHndl)->numTypes = numTypes;
  228.     
  229.     UseResFile (saveResFork);        // Restore the original order of open resource forks
  230.     return typesHndl;
  231. }
  232.  
  233. Boolean OpenableType (OSType fileType, TypeListHndl openableTypesHndl)
  234. {
  235.     short    i;
  236.     OSType    t, *tp;
  237.     
  238.     if (openableTypesHndl == NULL)
  239.         return FALSE;
  240.         
  241.     tp = &(*openableTypesHndl)->type[0];
  242.     for (i = (*openableTypesHndl)->numTypes; i > 0; i--, tp++) {
  243.         t = *tp;
  244.         if (fileType == 'fold' || fileType == 'disk') {
  245.             if (t == fileType)
  246.                 return TRUE;
  247.         } else if (t == '****' || t == fileType)
  248.             return TRUE;
  249.     }
  250.     return FALSE;        // If we got here, there's no match
  251. }
  252.  
  253. OSErr RefNumToFSSpec (short refNum, FSSpec *fss, Boolean *isResFork)
  254. {
  255.     FCBPBRec    pb;
  256.     OSErr        err;
  257.     
  258.     // See Inside Macintosh IV pp.178╨180 for documentation of PBGetFCBInfo
  259.     // NOTE:    There is an apparent typo there ╤ at the bottom of page 180, it says:
  260.     //
  261.     //            "FCBMdRByt (which corresponds to ioFCBFlags in the parameter
  262.     //            block for PBGetFCBInfo) contains flags that describe the status
  263.     //            of the file, as follows:╔"
  264.     //
  265.     //        But experience shows that these flags are returned in the HIGH BYTE
  266.     //        of the ioFCBFlags field, not the whole word (in effect, in its low byte)
  267.     
  268.     pb.ioCompletion = NULL;
  269.     pb.ioVRefNum = 0;            // 0 == check all volumes
  270.     pb.ioNamePtr = fss->name;    // Yes, we need the name of the file ╤ don't worry,
  271.                             //    HFSDispatch (in its guise of PBGetFCBInfo)
  272.                             //    doesn't move or purge memory (whew!)
  273.     pb.ioRefNum = refNum;
  274.     pb.ioFCBIndx = 0L;            // Get info on just this one file
  275.     
  276.     err = PBGetFCBInfoSync (&pb);    // NOTE:    For some strange reason, calling
  277.                                 //        PBGetFCBInfo (&pb, FALSE) here
  278.                                 //        instead gives us a major hang ╤ I
  279.                                 //        have a feeling this is the fault of
  280.                                 //        THINK C's glue routines but I'm not
  281.                                 //        going to bother finding out for sure╔
  282.     if (err != noErr)
  283.         return err;
  284.     
  285.     // Fill in the FSSpec ╤ note that fss->name has already been filled in
  286.     fss->vRefNum = pb.ioFCBVRefNum;
  287.     fss->parID = pb.ioFCBParID;    // Inside Macintosh IV implies that pb.ioVRefNum
  288.                             //    returns the volume refnum, but in fact the call
  289.                             //    to PBGetFCBInfo doesn't affect it.  This makes
  290.                             //    sense when you think about it ╤ if it DID return
  291.                             //    the volume refnum in ioVRefNum, you'd have
  292.                             //    to reset it to 0 in each of a sequence of indexed
  293.                             //    calls (with ioFCBIndx going from 1 to n == the
  294.                             //    number of open paths)
  295.     if (isResFork != NULL)
  296.         *isResFork = (pb.ioFCBFlags & 0x0200);
  297.         // 0x0200 == binary 00000010_00000000 ╤ as I mentioned above, it's the
  298.         //    HIGH byte that counts.  Bit 9 of the word == bit 1 of the high byte ╤ Inside
  299.         //    Macintosh IV (bottom of p.180) tells us "[bit] 1 ╔ [is set] if the entry
  300.         //    describes a resource fork"
  301.     
  302. }
  303.